Instalando os pacotes

# install.packages("base")
library(ggplot2)
# install.packages("corrplot")
library(corrplot)
## corrplot 0.92 loaded
# install.packages("fmsb")
library(fmsb)
# install.packages("ggplot2")
library(ggplot2)
# install.packages("dplyr")
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# install.packages("rmarkdown")
library(rmarkdown)

Preparar dados

tc <- read.table("./data/tc.txt", header = TRUE)
ts <- read.table("./data/ts.txt", header = TRUE)

dataframe_tempos <- cbind(tc, ts)

colnames(dataframe_tempos) <- c("chegada", "servico")

dataframe_tempos$chegada <- as.numeric(dataframe_tempos$chegada)
dataframe_tempos$servico <- as.numeric(dataframe_tempos$servico)
summary(dataframe_tempos)
##     chegada          servico     
##  Min.   : 0.000   Min.   : 8.00  
##  1st Qu.: 3.000   1st Qu.: 9.00  
##  Median : 5.000   Median :11.00  
##  Mean   : 4.628   Mean   :11.02  
##  3rd Qu.: 6.000   3rd Qu.:13.00  
##  Max.   :10.000   Max.   :14.00
colunas <- c(
  "valor_corte",
  "percentual_corte",
  "qtde_minimo_atendido",
  "algoritmo",
  "qtde_atendentes",
  "tempo_total",
  "tempo_total_da_fila_ocupada",
  "tempo_max_fila",
  "media_na_fila",
  "tamanho_max_fila",
  "tempo_atendente_ocioso_media"
)

Modelo de Entrada

Calculando os outliers

# Outliers da chegada
quantile_chegada <- quantile(dataframe_tempos$chegada, probs = c(.25, .50, .75), na.rm = FALSE)
amplitude_chegada <- max(dataframe_tempos$chegada) - min(dataframe_tempos$chegada)

# Outliers da chegada
quantile_servico <- quantile(dataframe_tempos$servico, probs = c(.25, .50, .75), na.rm = FALSE)
amplitude_servico <- max(dataframe_tempos$servico) - min(dataframe_tempos$servico)

Exploração dos dados

Criando data frame com medidas de posição e dispersão dos dados

df_medidas <- data.frame(
  Metrica = c("Média", "Desvio Padrão", "Variância", "Mediana", "Mínimo", "Máximo", "Amplitude", "Outlier Baixo Moderado", "Outlier Alto Moderado", "Outlier Baixo Extremo", "Outlier Alto Extremo"),
  TempoChegada = c(
    mean(dataframe_tempos$chegada),  # média
    sd(dataframe_tempos$chegada),  # desvio padrão
    var(dataframe_tempos$chegada),  # variância da amostra
    median(dataframe_tempos$chegada),  # mediana
    min(dataframe_tempos$chegada),  # minimo
    max(dataframe_tempos$chegada),  # maximo
    amplitude_chegada,  # amplitude
    quantile_chegada[1] - 1.5 * amplitude_chegada,
    quantile_chegada[3] + 1.5 * amplitude_chegada,
    quantile_chegada[1] - 3 * amplitude_chegada,
    quantile_chegada[3] + 3 * amplitude_chegada
  ),
  TempoServico = c(
    mean(dataframe_tempos$servico),  # média
    sd(dataframe_tempos$servico),  # desvio padrão
    var(dataframe_tempos$servico),  # variância da amostra
    median(dataframe_tempos$servico),  # mediana
    min(dataframe_tempos$servico),  # minimo
    max(dataframe_tempos$servico),  # maximo
    amplitude_servico,  # amplitude
    quantile_servico[1] - 1.5 * amplitude_servico,
    quantile_servico[3] + 1.5 * amplitude_servico,
    quantile_servico[1] - 3 * amplitude_servico,
    quantile_servico[3] + 3 * amplitude_servico
  )
)

Com o dataframe é possível identificar que o dataset não possui outliers.

Histograma

par(mfrow = c(1, 2))
hist(dataframe_tempos$chegada, main = "Histograma: tempos de chegada", xlab = "Tempo de chegada", ylab = "Frequência", col = "blue")
hist(dataframe_tempos$servico, main = "Histograma: tempos de serviço", xlab = "Tempo de serviço", ylab = "Frequência", col = "red")

### Utilizando os histogramas gerados podemos observar que os dados de chegada seguem uma distribuição normal, já o tempo de seviço é uma distribuição uniforme

Correlação

pairs(dataframe_tempos)

acf(dataframe_tempos$chegada, pl = TRUE)

acf(dataframe_tempos$servico, pl = TRUE)

corrplot(cor(dataframe_tempos), method = "number")

# Criando funções ## Simulador Computacional quantitativo ## Variavel: Quantidade de atendentes ## Mode: Os atendimentos são atendidos por ordem de chegada

simulador_computacional <- function(dados, qtde_atendentes) {
  fila <- data.frame()
  atendidos <- 0
  qtde_chegadas <- 0
  unidade_tempo <- 0
  tempo_total_da_fila_ocupada <- 0
  tempo_total_na_fila <- 0
  tamanho_max_fila <- 0
  tempo_max_fila <- 0
  tempo_atendente_ocioso <- 0
  atendentes <- data.frame(disponivel = rep(TRUE, qtde_atendentes), tempo_servico = rep(0, qtde_atendentes), tempo_atendimento = rep(0, qtde_atendentes))

  dados$soma_chegada <- cumsum(dados$chegada)

  while (atendidos < nrow(dados)) {
    while (!is.na(dados$soma_chegada[qtde_chegadas + 1]) && dados$soma_chegada[qtde_chegadas + 1] == unidade_tempo) {
      fila <- rbind(fila, dados[qtde_chegadas + 1,])
      qtde_chegadas <- qtde_chegadas + 1
    }

    if (nrow(fila) > 0) {
      tempo_total_da_fila_ocupada <- tempo_total_da_fila_ocupada + 1
      fila
    }

    if (nrow(fila) > tamanho_max_fila) {
      tamanho_max_fila <- nrow(fila)
    }

    for (i in 1:qtde_atendentes) {
      if (atendentes$disponivel[i]) {
        if (nrow(fila) > 0) {
          atendentes$tempo_servico[i] <- fila$servico[1]
          atendentes$disponivel[i] <- FALSE
          atendentes$tempo_atendimento[i] <- 0
          tempo_total_na_fila <- tempo_total_na_fila + (unidade_tempo - fila$soma_chegada[1])
          if ((unidade_tempo - fila$soma_chegada[1]) > tempo_max_fila) {
            tempo_max_fila <- unidade_tempo - fila$soma_chegada[1]
          }
          fila <- fila[-1,]
        } else {
          tempo_atendente_ocioso <- tempo_atendente_ocioso + 1
        }
      } else {
        atendentes$tempo_atendimento[i] <- atendentes$tempo_atendimento[i] + 1
        if (atendentes$tempo_atendimento[i] == atendentes$tempo_servico[i]) {
          atendidos <- atendidos + 1
          atendentes$disponivel[i] <- TRUE
          atendentes$tempo_atendimento[i] <- 0
          atendentes$tempo_servico[i] <- 0
        }
      }
    }

    unidade_tempo <- unidade_tempo + 1
  }

  return(data.frame(
    atendidos = atendidos,
    qtde_chegadas = qtde_chegadas,
    qtde_atendentes = qtde_atendentes,
    tempo_total = unidade_tempo,
    tempo_total_da_fila_ocupada = tempo_total_da_fila_ocupada,
    tempo_max_fila = tempo_max_fila,
    tempo_total_na_fila = tempo_total_na_fila,
    media_na_fila = tempo_total_na_fila / qtde_chegadas,
    tamanho_max_fila = tamanho_max_fila,
    tempo_atendente_ocioso = tempo_atendente_ocioso,
    tempo_atendente_ocioso_media = tempo_atendente_ocioso / qtde_atendentes,
    algoritmo = NA,
    valor_corte = NA,
    percentual_corte = NA,
    qtde_minimo_atendido = NA,
    metodo = NA
  ))
}

Simulador Computacional por prioridade

Variavel: Quantidade de atendentes

Mode: Os atendimentos são atendidos por ordem de chegada e prioridade, para cada QTDE_MINIMO_ATENDIDO chamados com tempo de serviço MENOR OU IGUAL ao VALOR_CORTE, um chamado com tempo de serviço MAIOR que VALOR_CORTE é atendido. Caso não tenha serviços na fila adequados, o primeiro da fila sera atendido.

simulador_computacional_prioridade_corte <- function(dados, qtde_atendentes, valor_corte, qtde_minimo_atendido = 2) {
  fila <- data.frame()
  atendidos <- 0
  qtde_chegadas <- 0
  unidade_tempo <- 0
  tempo_total_da_fila_ocupada <- 0
  tempo_total_na_fila <- 0
  tamanho_max_fila <- 0
  tempo_max_fila <- 0
  tempo_atendente_ocioso <- 0
  chamados_atendidos_corte <- 0
  atendentes <- data.frame(disponivel = rep(TRUE, qtde_atendentes), tempo_servico = rep(0, qtde_atendentes), tempo_atendimento = rep(0, qtde_atendentes))

  dados$soma_chegada <- cumsum(dados$chegada)

  while (atendidos < nrow(dados)) {
    while (!is.na(dados$soma_chegada[qtde_chegadas + 1]) && dados$soma_chegada[qtde_chegadas + 1] == unidade_tempo) {
      fila <- rbind(fila, dados[qtde_chegadas + 1,])
      qtde_chegadas <- qtde_chegadas + 1
    }

    if (nrow(fila) > 0) {
      tempo_total_da_fila_ocupada <- tempo_total_da_fila_ocupada + 1
      fila
    }

    if (nrow(fila) > tamanho_max_fila) {
      tamanho_max_fila <- nrow(fila)
    }

    for (i in 1:qtde_atendentes) {
      if (atendentes$disponivel[i]) {
        if (nrow(fila) > 0) {
          indice <- 1
          if (chamados_atendidos_corte < qtde_minimo_atendido) {
            for (j in seq_len(nrow(fila))) {
              if (fila$servico[j] <= valor_corte) {
                indice <- j
                chamados_atendidos_corte <- chamados_atendidos_corte + 1
                break
              }
            }
          } else {
            for (j in seq_len(nrow(fila))) {
              if (fila$servico[j] >= valor_corte) {
                indice <- j
                chamados_atendidos_corte <- 0
                break
              }
            }
          }

          atendentes$tempo_servico[i] <- fila$servico[indice]
          atendentes$tempo_servico[i] <- fila$servico[indice]
          atendentes$disponivel[i] <- FALSE
          atendentes$tempo_atendimento[i] <- 0
          tempo_total_na_fila <- tempo_total_na_fila + (unidade_tempo - fila$soma_chegada[indice])
          if ((unidade_tempo - fila$soma_chegada[indice]) > tempo_max_fila) {
            tempo_max_fila <- unidade_tempo - fila$soma_chegada[indice]
          }
          fila <- fila[-indice,]
        } else {
          tempo_atendente_ocioso <- tempo_atendente_ocioso + 1
        }
      } else {
        atendentes$tempo_atendimento[i] <- atendentes$tempo_atendimento[i] + 1
        if (atendentes$tempo_atendimento[i] == atendentes$tempo_servico[i]) {
          atendidos <- atendidos + 1
          atendentes$disponivel[i] <- TRUE
          atendentes$tempo_atendimento[i] <- 0
          atendentes$tempo_servico[i] <- 0
        }
      }
    }

    unidade_tempo <- unidade_tempo + 1
  }

  return(data.frame(
    atendidos = atendidos,
    qtde_chegadas = qtde_chegadas,
    qtde_atendentes = qtde_atendentes,
    tempo_total = unidade_tempo,
    tempo_total_da_fila_ocupada = tempo_total_da_fila_ocupada,
    tempo_max_fila = tempo_max_fila,
    tempo_total_na_fila = tempo_total_na_fila,
    media_na_fila = tempo_total_na_fila / qtde_chegadas,
    tamanho_max_fila = tamanho_max_fila,
    tempo_atendente_ocioso = tempo_atendente_ocioso,
    tempo_atendente_ocioso_media = tempo_atendente_ocioso / qtde_atendentes,
    algoritmo = NA,
    valor_corte = NA,
    percentual_corte = NA,
    qtde_minimo_atendido = NA,
    metodo = NA
  ))
}

Simulador com for i

simulador_computacional_iteracao <- function(qtde_atendentes, qtde_iteracao, percentual_corte = NA, qtde_minimo_atendido = 2, m = "median") {
  # Criando df com dados aleatórios e limpado-o, necessário para reutizar o método varias vezes sem
  # ter problemas com resido de dados no contexto
  df_simulados_temp <- rbind(simulador_computacional(gerar_numeros_aleatorios(nrow(dataframe_tempos)), qtde_atendentes))
  df_simulados_temp <- df_simulados_temp[0,]

  for (i in 1:qtde_iteracao) {
    if (!is.na(percentual_corte)) {
      temp <- gerar_numeros_aleatorios(nrow(dataframe_tempos))
      valor_corte <- quantile(temp$servico, probs = c(percentual_corte), na.rm = FALSE)
      df_simulados_temp <- rbind(df_simulados_temp, simulador_computacional_prioridade_corte(temp, qtde_atendentes, valor_corte, qtde_minimo_atendido))
    } else {
      df_simulados_temp <- rbind(df_simulados_temp, simulador_computacional(gerar_numeros_aleatorios(nrow(dataframe_tempos)), qtde_atendentes))
    }
  }

  if (m == "mean") {
    df_simulados_temp$metodo <- as.factor("mean")
    df_simulados_temp$atendidos <- mean(df_simulados_temp$atendidos)
    df_simulados_temp$qtde_chegadas <- mean(df_simulados_temp$qtde_chegadas)
    df_simulados_temp$qtde_atendentes <- mean(df_simulados_temp$qtde_atendentes)
    df_simulados_temp$tempo_total <- mean(df_simulados_temp$tempo_total)
    df_simulados_temp$tempo_total_da_fila_ocupada <- mean(df_simulados_temp$tempo_total_da_fila_ocupada)
    df_simulados_temp$tempo_max_fila <- mean(df_simulados_temp$tempo_max_fila)
    df_simulados_temp$tempo_total_na_fila <- mean(df_simulados_temp$tempo_total_na_fila)
    df_simulados_temp$media_na_fila <- mean(df_simulados_temp$media_na_fila)
    df_simulados_temp$tamanho_max_fila <- mean(df_simulados_temp$tamanho_max_fila)
    df_simulados_temp$tempo_atendente_ocioso <- mean(df_simulados_temp$tempo_atendente_ocioso)
    df_simulados_temp$tempo_atendente_ocioso_media <- mean(df_simulados_temp$tempo_atendente_ocioso_media)
  } else if (m == "median") {
    df_simulados_temp$metodo <- as.factor("median")
    df_simulados_temp$atendidos <- median(df_simulados_temp$atendidos)
    df_simulados_temp$qtde_chegadas <- median(df_simulados_temp$qtde_chegadas)
    df_simulados_temp$qtde_atendentes <- median(df_simulados_temp$qtde_atendentes)
    df_simulados_temp$tempo_total <- median(df_simulados_temp$tempo_total)
    df_simulados_temp$tempo_total_da_fila_ocupada <- median(df_simulados_temp$tempo_total_da_fila_ocupada)
    df_simulados_temp$tempo_max_fila <- median(df_simulados_temp$tempo_max_fila)
    df_simulados_temp$tempo_total_na_fila <- median(df_simulados_temp$tempo_total_na_fila)
    df_simulados_temp$media_na_fila <- median(df_simulados_temp$media_na_fila)
    df_simulados_temp$tamanho_max_fila <- median(df_simulados_temp$tamanho_max_fila)
    df_simulados_temp$tempo_atendente_ocioso <- median(df_simulados_temp$tempo_atendente_ocioso)
    df_simulados_temp$tempo_atendente_ocioso_media <- median(df_simulados_temp$tempo_atendente_ocioso_media)
  }

  if (!is.na(percentual_corte)) {
    df_simulados_temp$algoritmo <- as.factor("Chegada + Prioridade")
  } else {
    df_simulados_temp$algoritmo <- as.factor("Chegada")
  }

  df_simulados_temp$percentual_corte <- percentual_corte
  df_simulados_temp$qtde_minimo_atendido <- qtde_minimo_atendido

  df_simulados_temp <- df_simulados_temp[1,]
  rownames(df_simulados_temp) <- paste(df_simulados_temp$algoritmo, df_simulados_temp$percentual_corte, df_simulados_temp$qtde_minimo_atendido, df_simulados_temp$qtde_atendentes, sep="-")
  return(df_simulados_temp)
}

Gerador de Números Aleatórios

trunc <- function(x, ..., prec = 0) base::trunc(x * 10^prec, ...) / 10^prec;

gerar_numeros_aleatorios <- function(n) {
  # Gerar numeros aleatório utilizando uma distribuição normal
  chegada <- rnorm(n, df_medidas[1, c(2)], df_medidas[2, c(2)])
  servico <- runif(n, df_medidas[5, c(3)], df_medidas[6, c(3)])

  # Corrigir os números menores de 0.5 para 0
  chegada <- ifelse(chegada < 0.5, 0, chegada)
  servico <- ifelse(servico < 0.5, 0, servico)

  # Truncar os valores gerados
  chegada <- as.integer(trunc(chegada, prec = 0))
  servico <- as.integer(trunc(servico, prec = 0))

  return(data.frame(chegada, servico))
}

Validando gerador de números

Gerando histograma

df_numeros_aleatorios <- gerar_numeros_aleatorios(nrow(dataframe_tempos))

par(mfrow = c(1, 2))
hist(df_numeros_aleatorios$chegada, main = "Histograma: tempos de chegada", xlab = "Tempo de chegada", ylab = "Frequência", col = "blue")
hist(df_numeros_aleatorios$servico, main = "Histograma: tempos de serviço", xlab = "Tempo de serviço", ylab = "Frequência", col = "red")

### Utilizando os histogramas gerados podemos observar que os dados gerados de forma aleatória seguem o mesmo padrão dos dados originais

Correlação

pairs(df_numeros_aleatorios)

corrplot(cor(df_numeros_aleatorios), method = "number")

acf(df_numeros_aleatorios$chegada, pl = TRUE)

acf(df_numeros_aleatorios$servico, pl = TRUE)

Execução do Simulador

Executando simulador com os dados originais

df_simulado_original <- simulador_computacional(dataframe_tempos, 1)[, colunas]
rownames(df_simulado_original) <- "Original"

print(df_simulado_original)
##          valor_corte percentual_corte qtde_minimo_atendido algoritmo
## Original          NA               NA                   NA        NA
##          qtde_atendentes tempo_total tempo_total_da_fila_ocupada tempo_max_fila
## Original               1        3008                        2990           1840
##          media_na_fila tamanho_max_fila tempo_atendente_ocioso_media
## Original       926.068              154                            4

Executando simulador com os dados aleatorios

# Criando df com dados aleatórios e limpado-o, necessário para reutizar o método varias vezes sem
# ter problemas com resido de dados no contexto
df_simulados <- simulador_computacional(gerar_numeros_aleatorios(nrow(dataframe_tempos)), 1)
df_simulados <- df_simulados[0,]
qtde_atendentes <- 7
qtde_iteracao <- 3

for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao))
}

for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .10, qtde_minimo_atendido = 2))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .10, qtde_minimo_atendido = 3))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .10, qtde_minimo_atendido = 4))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .15, qtde_minimo_atendido = 2))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .15, qtde_minimo_atendido = 3))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .15, qtde_minimo_atendido = 4))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .25, qtde_minimo_atendido = 2))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .25, qtde_minimo_atendido = 3))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .25, qtde_minimo_atendido = 4))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .50, qtde_minimo_atendido = 2))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .50, qtde_minimo_atendido = 3))
}
for (i in 1:qtde_atendentes) {
  df_simulados <- rbind(df_simulados, simulador_computacional_iteracao(i, qtde_iteracao, percentual_corte = .50, qtde_minimo_atendido = 4))
}

Analisando resultados das simulações

df_simulados_analise <- df_simulados[,colunas]
# hist(df_simulados_analise$tempo_max_fila, main = "Histograma: tempos de chegada", xlab = "Tempo de chegada", ylab = "Frequência", col = "blue")
colunas2 <- c(
  "qtde_atendentes",
  "tempo_total",
  "tempo_total_da_fila_ocupada",
  "tempo_max_fila",
  "media_na_fila",
  "tamanho_max_fila",
  "tempo_atendente_ocioso_media"
)

df_todos_simulado <- rbind(df_simulado_original, df_simulados_analise)
data_grafico <- df_todos_simulado[, colunas2]

Correlação

# pairs(df_simulados[, c(3:11)])
corrplot(cor(data_grafico), method = "number")

### Podemos notar uma forte correlação entre a quantidade de atendentes e o tempo ocioso ### Também podemos ver uma forte correlação entre si nas métricas da fila, mostrando que, conforme o tamanho maximo fila diminui, o tempo médio e o tempo total da fila também diminuem. ### O tempo total do atendimento também diminui conforme o tempo da fila diminui.

Grafico relacionando o tempo total de atendimento com o tempo de ociosidade dos atendentes

data_grafico$qtde_atendentes <- as.factor(data_grafico$qtde_atendentes)

ggplot(data_grafico, aes(x=tempo_atendente_ocioso_media, y=tempo_total)) +
  geom_point(aes(col=qtde_atendentes), size=2)

### Com o gráfico podemos observar que as simulações com 2 atendentes possuio tempo de ociosidade próximo ao minimo e um tempo de atendimento total médio ### Já as simulações com 3 atendentes apresenta os melhores resultados, possuindo um tempo de atendimento total próximo ao minimo e um tempo ocioso baixo ### Podemos notar também que com 4 ou mais atendentes o valor total do atendimento continua próximo ao minimo porém aumentando mais o tempo de ociosidade dos atendentes

ggplot(data_grafico, aes(x=tamanho_max_fila, y=tempo_max_fila)) +
  geom_point(aes(col=qtde_atendentes), size=2)

### Observando esse segundo grafico podemos ver que as simulações com 1 atendente possuem o tempo maximo na fila muito alto, isso cai para menos da metade com 2 atendentes. ### Já com 3 atendentes, o tempo maximo e o tamanho maximo da fila ficam próximos do minimo. ### As simulações com 4 atendentes ou novamente não apresentam ganhos significativos

Como visto, 4 atendentes ou mais não apresentam ganhos, sendo assim iremos desconsidera-los da para frente

data_grafico$qtde_atendentes <- as.integer(data_grafico$qtde_atendentes)
data_grafico <- data_grafico[data_grafico$qtde_atendentes <=3,]
ggplot(data_grafico[data_grafico$qtde_atendentes == 1,], aes(x=tamanho_max_fila, y=tempo_max_fila)) +
  geom_point(aes(col=row.names(data_grafico[data_grafico$qtde_atendentes == 1,])), size=2) +
  geom_label(
    label=rownames(data_grafico[data_grafico$qtde_atendentes == 1,]),
    nudge_x = 0.25, nudge_y = 0.25)

ggplot(data_grafico[data_grafico$qtde_atendentes == 2,], aes(x=tamanho_max_fila, y=tempo_max_fila)) +
  geom_point(aes(col=row.names(data_grafico[data_grafico$qtde_atendentes == 2,])), size=2) +
  geom_label(
    label=rownames(data_grafico[data_grafico$qtde_atendentes == 3,]),
    nudge_x = 0.25, nudge_y = 0.25
  )

ggplot(data_grafico[data_grafico$qtde_atendentes == 3,], aes(x=tamanho_max_fila, y=tempo_max_fila)) +
  geom_point(aes(col=row.names(data_grafico[data_grafico$qtde_atendentes == 3,])), size=2) +
  geom_label(
    label=rownames(data_grafico[data_grafico$qtde_atendentes == 3,]),
    nudge_x = 0.25, nudge_y = 0.25)

ggplot(data_grafico[data_grafico$qtde_atendentes == 1,], aes(x=tempo_atendente_ocioso_media, y=tempo_total)) +
  geom_point(aes(col=row.names(data_grafico[data_grafico$qtde_atendentes == 1,])), size=2) +
  geom_label(
    label=rownames(data_grafico[data_grafico$qtde_atendentes == 1,]),
    nudge_x = 0.25, nudge_y = 0.25)

ggplot(data_grafico[data_grafico$qtde_atendentes == 2,], aes(x=tempo_atendente_ocioso_media, y=tempo_total)) +
  geom_point(aes(col=row.names(data_grafico[data_grafico$qtde_atendentes == 2,])), size=2) +
  geom_label(
    label=rownames(data_grafico[data_grafico$qtde_atendentes == 3,]),
    nudge_x = 0.25, nudge_y = 0.25
  )

ggplot(data_grafico[data_grafico$qtde_atendentes == 3,], aes(x=tempo_atendente_ocioso_media, y=tempo_total)) +
  geom_point(aes(col=row.names(data_grafico[data_grafico$qtde_atendentes == 3,])), size=2) +
  geom_label(
    label=rownames(data_grafico[data_grafico$qtde_atendentes == 3,]),
    nudge_x = 0.25, nudge_y = 0.25)

# Grafico de rede das simulações de 1 atendente
data_grafico_spider_1 <- rbind(
  c(7, min(df_todos_simulado$tempo_total), min(df_todos_simulado$tempo_total_da_fila_ocupada), min(df_todos_simulado$tempo_max_fila), 0, 0, 0),
  c(0, max(df_todos_simulado$tempo_total), max(df_todos_simulado$tempo_total_da_fila_ocupada), max(df_todos_simulado$tempo_max_fila), max(df_todos_simulado$media_na_fila), max(df_todos_simulado$tamanho_max_fila), max(df_todos_simulado$tempo_atendente_ocioso_media)),
  data_grafico[data_grafico$qtde_atendentes == 1,])

library(RColorBrewer)
coul <- brewer.pal(12, "Set3")
colors_border <- coul
library(scales)
colors_in <- alpha(coul,0)

# plot with default options:
radarchart( data_grafico_spider_1  , axistype=2 ,
            #custom polygon
            pcol=colors_border , pfcol=colors_in , plwd=4 , plty=1,
            #custom the grid
            cglcol="grey", cglty=1, axislabcol="black", cglwd=0.8,
            #custom labels
            vlcex=0.8
)

# Add a legend
legend(x=1.3, y=1, legend = rownames(data_grafico_spider_1[-c(1,2),]), bty = "n", pch=20 , col=colors_border , text.col = "grey", cex=1.2, pt.cex=3)

# Grafico de rede das simulações de 2 atendente
data_grafico_spider_2 <- rbind(
  c(7, min(df_todos_simulado$tempo_total), min(df_todos_simulado$tempo_total_da_fila_ocupada), min(df_todos_simulado$tempo_max_fila), 0, 0, 0),
  c(0, max(df_todos_simulado$tempo_total), max(df_todos_simulado$tempo_total_da_fila_ocupada), max(df_todos_simulado$tempo_max_fila), max(df_todos_simulado$media_na_fila), max(df_todos_simulado$tamanho_max_fila), max(df_todos_simulado$tempo_atendente_ocioso_media)),
  data_grafico[data_grafico$qtde_atendentes == 2,])

# plot with default options:
radarchart( data_grafico_spider_2  , axistype=2 ,
            #custom polygon
            pcol=colors_border , pfcol=colors_in , plwd=4 , plty=1,
            #custom the grid
            cglcol="grey", cglty=1, axislabcol="black", cglwd=0.8,
            #custom labels
            vlcex=0.8
)

# Add a legend
legend(x=1.3, y=1, legend = rownames(data_grafico_spider_2[-c(1,2),]), bty = "n", pch=20 , col=colors_border , text.col = "grey", cex=1.2, pt.cex=3)

# Grafico de rede das simulações de 3 atendente
data_grafico_spider_3 <- rbind(
  c(7, min(df_todos_simulado$tempo_total), min(df_todos_simulado$tempo_total_da_fila_ocupada), min(df_todos_simulado$tempo_max_fila), 0, 0, 0),
  c(0, max(df_todos_simulado$tempo_total), max(df_todos_simulado$tempo_total_da_fila_ocupada), max(df_todos_simulado$tempo_max_fila), max(df_todos_simulado$media_na_fila), max(df_todos_simulado$tamanho_max_fila), max(df_todos_simulado$tempo_atendente_ocioso_media)),
  data_grafico[data_grafico$qtde_atendentes == 3,])

# plot with default options:
radarchart( data_grafico_spider_3, axistype=2 ,
            #custom polygon
            pcol=colors_border , pfcol=colors_in , plwd=4 , plty=1,
            #custom the grid
            cglcol="grey", cglty=1, axislabcol="black", cglwd=0.8,
            #custom labels
            vlcex=0.8
)

# Add a legend
legend(x=1, y=1, legend = rownames(data_grafico_spider_3[-c(1,2),]), bty = "n", pch=20 , col=colors_border , text.col = "grey", cex=1.2, pt.cex=3)